using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Microblaze.Elf
{
  public class ElfSymbolTableEntry : ElfFormatEntity
  {
    public enum SymbolBinding
    {
      STB_LOCAL   = 0,
      STB_GLOBAL  = 1,
      STB_WEAK    = 2,
      STB_LOPROC  = 13,
      STB_HIPROC  = 15
    }

    public enum SymbolType
    {
      STT_NOTYPE  = 0,
      STT_OBJECT  = 1,
      STT_FUNC    = 2,
      STT_SECTION = 3,
      STT_FILE    = 4,
      STT_LOPROC  = 13,
      STT_HIPROC  = 15
    }

    public static uint Elf32_St_Bind(uint i)
    {
      return (i >> 4);
    }

    public static uint Elf32_St_Type(uint i)
    {
      return (i & 0xF);
    }

    public static uint Elf32_St_Info(uint b, uint t)
    { 
      return ((b << 4) + (t & 0xF));
    }

    private uint st_name;
    private uint st_value;
    private uint st_size;    
    private byte st_info;
    private byte st_other;

    public byte St_other
    {
      get { return st_other; }      
    }
    private ushort st_shndx;

    public ushort St_shndx
    {
      get { return st_shndx; }      
    }

    public uint St_value
    {
      get { return st_value; }      
    }

    public uint St_size
    {
      get { return st_size; }      
    }

    public string Name
    {
      get { return ElfFile.GetNameFromSymbolStringTable(this.st_name); }
    }

    public SymbolBinding Binding
    {
      get { return (SymbolBinding) Elf32_St_Bind(st_info); }
    }

    public SymbolType Type
    {
      get { return (SymbolType) Elf32_St_Type(st_info); }
    }

    public ElfSymbolTableEntry(ElfFile elfFile)
      : base(elfFile)
    {
    }

    public void Read()
    {
      st_name = ReadElf32Word(ElfFile.Reader);
      st_value = ReadElf32Addr(ElfFile.Reader);
      st_size = ReadElf32Word(ElfFile.Reader);
      st_info = ReadByte(ElfFile.Reader);
      st_other = ReadByte(ElfFile.Reader);
      st_shndx = ReadElf32Half(ElfFile.Reader);
    }

    public override string ToString()
    {
      return string.Format(
        "{0} - value: {1} size: {2} bind: {3} type: {4} index: {5}", 
        Name,
        st_value,
        st_size,
        Binding,
        Type,
        st_shndx
        );
    }
  }
}
